package com.common.utils;

import java.sql.Timestamp;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.Date;
import java.util.GregorianCalendar;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * 日期工具类
 * <p>Description:与日期相关的功能实现</p>
 * @version 1.0
 */

public class DateUtils {
	private static Calendar ca = Calendar.getInstance();
	/** 当前年**/
	public static String YEAR = "";
	/** 当前月**/
	public static String MONTH = "";
	/** 当前日期**/
	public static String DATE = "";
	/** 当前日期前一天**/
	public static String YESTERDAY = "";
	
	/** 标签 星期 下拉列表 设置 listKey="id" listValue="name"  list="@类的全路径@变量" **/
	public static final List<Map<String,String>> WEEKLIST = new ArrayList<Map<String,String>>(){
		private static final long serialVersionUID = 1L;
		{
			add(new HashMap<String, String>() {
				private static final long serialVersionUID = 1L;
				{
					put("id", "1");
					put("name", "星期一");
				}
			});
			add(new HashMap<String, String>() {
				private static final long serialVersionUID = 1L;
				{
					put("id", "2");
					put("name", "星期二");
				}
			});
			add(new HashMap<String, String>() {
				private static final long serialVersionUID = 1L;
				{
					put("id", "3");
					put("name", "星期三");
				}
			});
			add(new HashMap<String, String>() {
				private static final long serialVersionUID = 1L;
				{
					put("id", "4");
					put("name", "星期四");
				}
			});
			add(new HashMap<String, String>() {
				private static final long serialVersionUID = 1L;
				{
					put("id", "5");
					put("name", "星期五");
				}
			});
			add(new HashMap<String, String>() {
				private static final long serialVersionUID = 1L;
				{
					put("id", "6");
					put("name", "星期六");
				}
			});
			add(new HashMap<String, String>() {
				private static final long serialVersionUID = 1L;
				{
					put("id", "7");
					put("name", "星期七");
				}
			});
		}
	};
	
	/** 标签 显示1-7对应 星期 列表 设置 listKey="id" listValue="name"  list="@类的全路径@变量.get(属性名)" **/
	public static final Map<String, String> WEEKMAP = new HashMap<String, String>() {
		protected static final long serialVersionUID = 1L;
		{
			put("1", "星期一");
			put("2", "星期二");
			put("3", "星期三");
			put("4", "星期四");
			put("5", "星期五");
			put("6", "星期六");
			put("7", "星期日");
		}

	}; 
	
	static{
		YESTERDAY = getYesterday();
		ca.setTime(new Date());
		DATE = formatDate(ca.getTime(),"yyyy-MM-dd");
		YEAR = formatDate(ca.getTime(),"yyyy");
		MONTH = formatDate(ca.getTime(),"MM");
	}
	/**
	 * 方法名:getYesterday
	 * 方法作用:得到当前日期前一天
	 * @return 字符串类型日期
	 */
	public static String getYesterday(){
		Calendar newCa = Calendar.getInstance();
		newCa.setTime(new Date());
		newCa.add(Calendar.DATE,-1);
		return formatDate(newCa.getTime(),"yyyy-MM-dd");
	}
	
	
	/**
	 * 方法名:getYesterday
	 * 方法作用:得到指定日期前一天
	 * @param date	传入字符串类型日期
	 * @return 字符串类型指定日期前一天
	 * @throws ParseException 
	 */
	public static String getYesterday(String date) throws ParseException{
		Calendar newCa = Calendar.getInstance();
		newCa.setTime(StringToDate("yyyy-MM-dd",date));
		newCa.add(Calendar.DATE,-1);
		return formatDate(newCa.getTime(),"yyyy-MM-dd");
	}
	
	/**
	* <p>方法作用:日期对象转换为指定格式的字符串日期</p>
	* <br>参数格式为：yyyy/MM/dd HH:mm:ss或yyyy-MM-dd HH:mm:ss</br>
	* <br>样例:<br>
	* formatDate(new Date(),"yyyy-MM-dd")= 服务器当前时间，格式为yyyy-MM-dd;
	* formatDate(toDate(2010,1,27),"yyyy-MM-dd") = "2010-01-27";
	* formatDate(toDate("2010-01-27 10:15:24","yyyy-MM-dd HH:mm:ss"),"yyyy-MM-dd HH:mm:ss") = "2010-01-27 10:15:24";
	* @param sule	格式化规则
	* @param date	Date类型日期
	* @return	字符串型日期
	*/
	public static String formatDate(Date date,String sule){
		SimpleDateFormat sdf = new SimpleDateFormat(sule);
		return sdf.format(date);
	}
	
	/**
	 * 方法名:formatDate
	 * 方法作用:格式化日期
	 * @param sule	格式化规则
	 * @param date	字符串类型日期
	 * @return	字符串型日期
	 * @throws ParseException 
	 */
	public static String formatDate(String date,String sule){
		String newDate = "";
		try {
			SimpleDateFormat sdf = new SimpleDateFormat(sule);
			newDate = sdf.format(sdf.parse(date));
		} catch (ParseException e) {
			e.printStackTrace();
		}
		return newDate;
	}
	
	/**
	 * 方法名:StringToDate
	 * 方法作用:字符串日期格式化为指定规则日期
	 * <p>字符串类型的日期转换为指定格式的日期对象</p>
	 * <br>参数格式为：yyyy/MM/dd HH:mm:ss或yyyy-MM-dd HH:mm:ss或yyyy/MM/dd或yyyy-MM-dd<br>
	 * <br>样例:<br>
	 * StringToDate("yyyy/MM/dd HH:mm:ss","2010/01/01 20:10:02")=Fri Jan 01 20:10:02 CST 2010<br>
	 * StringToDate("yyyy-MM-dd","2010-01-01")=Sat Jan 01 00:00:00 CST 2010<br>
	 * @param sule	格式化规则
	 * @param date	字符串型日期
	 * @return	Date 日期对象
	 */
	public static Date StringToDate(String sule,String date){
		Date newDate = null;
		try {
			SimpleDateFormat sdf = new SimpleDateFormat(sule);
			newDate = sdf.parse(date);
		} catch (ParseException e) {
			e.printStackTrace();
		}
		return newDate;
	}
	
	/**
	 * <p>将整数类型的年、月、日,组合为日期格式的对象</p>
	 * <br>样例:<br>
	 * toDate(2010,12,14)=Tue Dec 14 00:00:00 CST 2010;<br>
	 * @param p_year int 年度
	 * @param p_month int 月份
	 * @param p_day int 日
	 * @return Date 组合后的日期
	 */
	public static Date toDate(int p_year,int p_month,int p_day) {
		Calendar _xmas = new GregorianCalendar(p_year,p_month-1,p_day);		
        return _xmas.getTime();		
	}
	
	/**
	 * <p>将字符串类型的年、月、日,组合为日期格式的对象</p>
	 * <br>样例:<br>
	 * <font color="red">当传入字符串为空时，没有进行处理</font>
	 * toDate("2010","12","14")=Tue Dec 14 00:00:00 CST 2010;<br>
	 * @param p_year String 年度
	 * @param p_month String 月份
	 * @param p_day String 日
	 * @return Date 组合后的日期
	 */
	public static Date toDate(String p_year,String p_month,String p_day) {
		return toDate(Integer.parseInt(p_year),Integer.parseInt(p_year),Integer.parseInt(p_day));        		
	}
	
	/**
	* <p>根据指定日期获得日历对象</p>
	* <br>样例:<br>
	* getCalendar(new Date("2010-01-27 10:15:24","yyyy-MM-dd HH:mm:ss")=Calendar;<br>
	* @param date Date 日期
	* @return Calendar 日历对象
	*/
	public static Calendar getCalendar(Date date){
		Calendar _calendar = Calendar.getInstance();
		_calendar.setTime(date);
		return _calendar;		
	}
	
   /**
	* <p>获得指定日期的年份字符串</p>
	* <br>样例:<br>
	* getYear(new Date())="2010";<br>
	* @param p_date Date 日期对象
	* @return String 日期的年份
	*/
	public static String getYear(Date date) {
		return formatDate(date,"yyyy");
	}
	
   /**
	* <p>获得指定日期的月份字符串,不足2位,前面补0</p>
	* <br>样例:<br>
	* getMonth(new Date())="01";<br>
	* @param date Date 日期
	* @return String 日期的月份
	*/
	public static String getMonth(Date date) {
		return formatDate(date,"MM");
	}
	
   /**
	* <p>获得指定日期的日字符串，不足2位，前面补0</p>
	* <br>样例:<br>
	* getDay(new Date())="02";<br>
	* @param date Date 日期
	* @return String 日期的日部分
	*/
	public static String getDay(Date date) {
		return formatDate(date,"dd");
	}
	
	/**
	 * <p>获得指定日期的小时字符串，不足2位，前面补0</p>
	 * <br>样例:<br>
	 * getHours(new Date())="12";<br>
	 * @param date Date 日期
	 * @return String 日期的小时
	 */
	public static String getHours(Date date) {
		return formatDate(new Date(), "HH");
	}	
	
   /**
	* <p>获得指定日期的分钟字符串，不足2位，前面补0</p>
	* <br>样例:<br>
	* getMinutes(new ate())="20";<br>
	* @param date Date 日期
	* @return String 日期的分钟
	*/
	public static String getMinutes(Date date) {
		return formatDate(new Date(), "mm");
	}	
	
	/**
	* <p>获得指定日期的秒字符串，不足2位，前面补0</p>
	* <br>样例:<br>
	* getSeconds(new Date())="30";<br>
	* @param date Date 日期
	* @return String 日期的秒
	*/
	public static String getSeconds(Date date) {
		return formatDate(new Date(), "ss");
	}
	
	/****************************（三）计算日期**********************************************/	
	/**
	 * <p>获得两个日期之间相差天数</p>
	 * <br>样例:<br>
	 * getDateDiff(toDate("2010-01-27","yyyy-MM-dd"), toDate("2010-01-29","yyyy-MM-dd"))= 2;<br>
	 * getDateDiff(toDate("2010-01-31","yyyy-MM-dd"), toDate("2010-01-29","yyyy-MM-dd"))= -2;<br>
	 * @param p_dateStart Date 起始日期
	 * @param p_dateEnd Date 结束日期
	 * @return long 两个日期之间相差的天数
	 */
	public static long getDateDiff(Date p_dateStart, Date p_dateEnd) throws Exception{
		if (p_dateStart==null) throw new Exception("Error:");
		if (p_dateEnd==null)  throw new Exception("Error:");		
		long _ldate1 = p_dateStart.getTime();
		long _ldate2 = p_dateEnd.getTime();
		long _iDatenum = 0;
		_iDatenum = (long)((_ldate2 - _ldate1)/86400000);
		return _iDatenum;
	}
	
	/**
	 * <p>获得两个日期之间相差小时数</p>
	 * <p>样例</p>
	 * Timestamp t1 = new TimeStamp(2010-1900, 2, 8, 10, 12, 0, 0);<br>
	 * Timestamp t2 = new TimeStamp(2010-1900, 2, 9, 10, 12, 0, 0);<br>
	 * getHourDiff(t1, t2) = 24;<br>
	 * getHourDiff(t2, t1) = -24;<br>
	 * 
	 * @param p_t1 前一个日期
	 * @param p_t2 后一个日期
	 * @return long 两个日期之间相差小时数
	 */
	public static long getHourDiff(Timestamp p_t1,Timestamp p_t2){
		long t1_=p_t1.getTime();
		long t2_=p_t2.getTime();
		return (t2_-t1_)/(60*60*1000);		 
	}
	
	/**
	 * <p>获得两个日期之间相差分钟数</p>
	 * <p>样例</p>
	 * Timestamp t1 = new TimeStamp(2010-1900, 2, 8, 10, 12, 0, 0);<br>
	 * Timestamp t2 = new TimeStamp(2010-1900, 2, 9, 10, 12, 0, 0);<br>
	 * getMinuteDiff(t1, t2) = 1440;<br>
	 * getMinuteDiff(t2, t1) = -1440;<br>
	 * 
	 * @param p_t1 前一个日期
	 * @param p_t2 后一个日期
	 * @return long 两个日期之间相差分钟数
	 */
	public static long getMinuteDiff(Timestamp p_t1,Timestamp p_t2){
		long t1_=p_t1.getTime();
		long t2_=p_t2.getTime();
		return ((t2_-t1_)/(60*1000));		 
	}
	
	/**
	* <p>获得指定日期的星期</p>
	* <br>样例:<br>
	* getWeek(toDate(2010,01,27))="星期三";<br>
	* @param p_date Date 指定的日期
	* @return String 日期的星期
	*/
	public static String getWeek(Date p_date) {		
		Calendar _cal1 = Calendar.getInstance();
		String _chiweek = null;	
		_cal1.setTime(p_date);
		int _bh = _cal1.get(Calendar.DAY_OF_WEEK);
		switch (_bh) {
			case 1 :
				_chiweek = "星期日";
				break;
			case 2 :
				_chiweek = "星期一";
				break;
			case 3 :
				_chiweek = "星期二";
				break;
			case 4 :
				_chiweek = "星期三";
				break;
			case 5 :
				_chiweek = "星期四";
				break;
			case 6 :
				_chiweek = "星期五";
				break;
			case 7 :
				_chiweek = "星期六";
				break;
		}
		return _chiweek;
	}

	/**
	* <p>获得指定字符串日期的星期</p>
	* <br>样例:<br>
	* getWeek("2010-01-03","yyyy-MM-dd")="星期日";<br>
	* getWeek("2010/01/01 20:10:02","yyyy/MM/dd HH:mm:ss")="星期五";<br>
	* @param p_date String 日期
	* @param p_format String 格式化类型 
	* @return String  日期的星期
	*/
	public static String getWeek(String p_date, String p_format) {
		try {
			return getWeek(StringToDate(p_date,p_format));
		} catch (Exception e) {
			e.printStackTrace();
			return null;
		}		
	}
	
	/**
	* <p>获得指定日期是今年的第几周</p>
	* <br>样例:<br>
	* getWeekOfYear(toDate("2010-01-27","yyyy-MM-dd"))=5;<br>
	* @param p_date Date 日期
	* @return int 周数
	*/
	public static int getWeekOfYear(Date p_date) {			
		Calendar _cal = Calendar.getInstance();
		_cal.setTime(p_date);
		return _cal.get(Calendar.WEEK_OF_YEAR);
	}
	
	/** syl
	* <p>获得指定年有多少周</p>	
	* <br>样例:<br>
	* getWeekNumbersOfYear(2010)=53;<br>
	* @param year 年度
	* @return int 周数
	*/
	public static int getWeekNumbersOfYear(int year) {
		GregorianCalendar cal = new GregorianCalendar(year,12,31);
		return cal.getMaximum(GregorianCalendar.WEEK_OF_YEAR);
	}
	
	/**
	* <p>获取指定年月最后一天的日期</p>
	* <br>样例:<br>
	* getLastDateOfMonth(2010, 02)=Sun Feb 28 00:00:00 CST 2010;<br>
	* @param p_year int 年
	* @param p_month int 月
	* @return Date 指定年月的最后一天日期
	*/
	public static Date getLastDateOfMonth(int p_year, int p_month) {		
		int _day = 0;
		boolean _blrn = false; //是否为闰年
		if ((p_month < 1) || (p_month > 12)) {
			return null;
		}
		_blrn = ((p_year % 4 == 0) || (p_year % 100 == 0)) && p_year % 400 == 0?true:false;
		switch (p_month){
			case 2:
				_day = _blrn?29:28;
				break;
			case 4:
			case 6:
			case 9:
			case 11:
				_day = 30;
				break;
			default:
				_day = 31;
		}
		return StringToDate("yyyy-MM-dd",p_year + "-" + p_month + "-" + _day);
	}
	
	/**
	 * <p>获取指定年月最后一天的日期</p>
	 * <br>样例:<br>
	 * getLastStrDateOfMonth(2010, 02)=2010-02-28;<br>
	 * @param p_year int 年
	 * @param p_month int 月
	 * @return String 指定年月的最后一天日期
	 */
	public static String getLastStrDateOfMonth(int p_year, int p_month) {		
		int _day = 0;
		boolean _blrn = false; //是否为闰年
		if ((p_month < 1) || (p_month > 12)) {
			return null;
		}
		_blrn = ((p_year % 4 == 0) || (p_year % 100 == 0)) && p_year % 400 == 0?true:false;
		switch (p_month){
		case 2:
			_day = _blrn?29:28;
			break;
		case 4:
		case 6:
		case 9:
		case 11:
			_day = 30;
			break;
		default:
			_day = 31;
		}
		return formatDate(p_year + "-" + p_month + "-" + _day,"yyyy-MM-dd");
	}
	
	/**
	 * <p>返回指定年的天数</p>
	 * <br>样例:<br>
	 * getDaysOfYear(2008)=366;<br>
	 * getDaysOfYear(2009)=365;<br>
	 * @param p_year
	 * @return int 指定年的天数
	 * @throws Exception
	 */
	public static int getDaysOfYear(int p_year) throws Exception{
		return (p_year % 4 == 0 && p_year % 100 != 0 )|| p_year % 400 == 0?366:365;
	}
	
	/**
	 * <p>在指定日期上添加月</p>
	 * <br>样例:<br>
	 * @param p_date 日期对象
	 * @param p_amount 月数（正、负均可）
	 * @return Date 日期对象
	 */
	 public static Date addMonths(Date p_date, int p_amount) {
		 return add(p_date, Calendar.MONTH, p_amount);
	 }
	 /**
	  * <p>在指定日期上添加月</p>
	  * <br>样例:<br>
	  * @param sule String 日期格式化规则
	  * @param p_date 日期对象
	  * @param p_amount 月数（正、负均可）
	  * @return Date 日期对象
	  */
	 public static Date addMonths(String sule,String p_date, int p_amount) {
		 return add(StringToDate(sule, p_date), Calendar.MONTH, p_amount);
	 }
	 
	 /**
	  * <p>在指定日期上添加周</p>
	  * <br>样例:<br>
	  * @param p_date 日期对象
	  * @param p_amount 周数（正、负均可）
	  * @return Date 日期对象
	  */
	 public static Date addWeeks(Date p_date, int p_amount) {
        return add(p_date, Calendar.WEEK_OF_YEAR, p_amount);
     }
	 
	 /**
	  * <p>在指定日期上添加周</p>
	  * <br>样例:<br>
	  * @param sule String 日期格式化规则
	  * @param p_date 日期对象
	  * @param p_amount 周数（正、负均可）
	  * @return Date 日期对象
	  */
	 public static Date addWeeks(String sule,String p_date, int p_amount) {
		 return add(StringToDate(sule, p_date), Calendar.WEEK_OF_YEAR, p_amount);
	 }
	 
	/**
	 * <p>在指定日期上添加天</p>
	 * <br>样例:<br>
	 * @param p_date 日期对象
	 * @param p_amount 天数（正、负均可）
	 * @return Date 日期对象
	 */
    public static Date addDays(Date p_date, int p_amount) {
        return add(p_date, Calendar.DAY_OF_MONTH, p_amount);
    }
    
    /**
     * <p>在指定日期上添加天</p>
     * <br>样例:<br>
     * @param sule String 日期格式化规则
     * @param p_date 日期对象
     * @param p_amount 天数（正、负均可）
     * @return Date 日期对象
     */
    public static Date addDays(String sule,String p_date, int p_amount) {
    	return add(StringToDate(sule, p_date), Calendar.DAY_OF_MONTH, p_amount);
    }
    
	/**
	 * <p>在指定日期上添加小时</p>
	 * <br>样例:<br>
	 * @param p_date Date 日期对象
	 * @param p_amount int 小时数（正、负均可）
	 * @return Date 日期对象
	 */
    public static Date addHours(Date p_date, int p_amount) {
        return add(p_date, Calendar.HOUR_OF_DAY, p_amount);
    }

    /**
     * <p>在指定日期上添加小时</p>
     * <br>样例:<br>
     * @param sule String 日期格式化规则
     * @param p_date String 日期对象
     * @param p_amount int 小时数（正、负均可）
     * @return Date 日期对象
     */
    public static Date addHours(String sule,String p_date, int p_amount) {
    	return add(StringToDate(sule, p_date), Calendar.HOUR_OF_DAY, p_amount);
    }
    
    /**
	 * <p>在指定日期上添加分钟</p>
	 * <br>样例:<br>
     * @param p_date Date 日期对象
     * @param p_amount int 分钟数（正、负均可）
     * @return Date 日期对象
     */
    public static Date addMinutes(Date p_date, int p_amount) {
        return add(p_date, Calendar.MINUTE, p_amount);
    }
    /**
     * <p>在指定日期上添加分钟</p>
     * <br>样例:<br>
     * @param sule String 日期格式化规则
     * @param p_date String 日期对象
     * @param p_amount int 分钟数（正、负均可）
     * @return Date 日期对象
     */
    public static Date addMinutes(String sule,String p_date, int p_amount) {
    	return add(StringToDate(sule, p_date), Calendar.MINUTE, p_amount);
    }
    
    /**
	 * <p>在指定日期上添加秒</p>
	 * <br>样例:<br>
     * @param p_date Date 日期对象
     * @param p_amount int 秒数（正、负均可）
     * @return Date 日期对象
     */
    public static Date addSeconds(Date p_date, int p_amount) {
        return add(p_date, Calendar.SECOND, p_amount);
    }
    /**
     * <p>在指定日期上添加秒</p>
     * <br>样例:<br>
     * @param sule String 日期格式化规则
     * @param p_date String 日期对象
     * @param p_amount int 秒数（正、负均可）
     * @return Date 日期对象
     */
    public static Date addSeconds(String sule,String p_date, int p_amount) {
    	return add(StringToDate(sule, p_date), Calendar.SECOND, p_amount);
    }
    
    /**
     * <p>在指定日期上添加域的数量</p>
     * <br>样例:<br>
     * add(toDate(2010,1,27),Calendar.DAY_OF_MONTH, -5)=Fri Jan 22 00:00:00 CST 2010;<br>
     * @param p_date Date 日期对象
     * @param p_calendarField int calendar域 例如：DAY_OF_WEEK 或 DAY_OF_YEAR 
     * @param p_amount int 数量（正、负均可）
     * @return Date 日期对象
     */
    private static Date add(Date p_date, int p_calendarField, int p_amount) {
        if (p_date == null) {
            throw new IllegalArgumentException("The date must not be null");
        }
        Calendar c = Calendar.getInstance();
        c.setTime(p_date);
        c.add(p_calendarField, p_amount);
        return c.getTime();
    }
    /****************************（四）更改日期**********************************************/	
    /**
     * <p>更改日期为指定年</p>
	 * <br>样例:<br>
	 * setYears(toDate("2010-01-27 10:00:00","yyyy-MM-dd hh:mm:ss"), 2009)=Tue Jan 27 10:00:00 CST 2009;<br>
     * @param p_date Date 日期对象
     * @param p_amount int 年
     * @return Date 日期对象
     */
    public static Date setYears(Date p_date, int p_amount) {
        return set(p_date, Calendar.YEAR, p_amount);
    }
    
    /**
     * <p>更改日期为指定月</p>
     * <br>样例:<br>
     * setMonths(toDate("2010-01-27 10:00:00","yyyy-MM-dd hh:mm:ss"), 5)=Thu May 27 10:00:00 CST 2010;<br>
     * @param p_date Date 日期对象
     * @param p_amount int 月
     * @return Date 日期对象
     */
    public static Date setMonths(Date p_date, int p_amount) {
        return set(p_date, Calendar.MONTH, p_amount-1);
    }
    
    /**
     * <p>更改日期为指定日</p>
     * <br>样例:<br>
     * setDays(toDate("2010-01-27 10:00:00","yyyy-MM-dd hh:mm:ss"), 5)=Tue Jan 05 10:00:00 CST 2010;<br>
     * @param p_date Date 日期对象
     * @param p_amount int 日
     * @return Date 日期对象
     */
    public static Date setDays(Date p_date, int p_amount) {
        return set(p_date, Calendar.DAY_OF_MONTH, p_amount);
    }

    /**
     * <p>更改日期为指定小时</p>
     * <br>样例:<br>
     * setHours(toDate("2010-01-27 10:00:00","yyyy-MM-dd hh:mm:ss"), 17)=Wed Jan 27 17:00:00 CST 2010;<br>
     * @param p_date Date 日期对象
     * @param p_amount int 小时
     * @return Date 日期对象
     */
    public static Date setHours(Date p_date, int p_amount) {
        return set(p_date, Calendar.HOUR_OF_DAY, p_amount);
    }
    
    /**
     * <p>更改日期为指定分钟</p>
     * <br>样例:<br>
     * setMinutes(toDate("2010-01-27 10:00:00","yyyy-MM-dd hh:mm:ss"), 40)=Wed Jan 27 10:40:00 CST 2010;<br>
     * @param p_date Date 日期对象
     * @param p_amount int 分钟
     * @return Date 日期对象
     */
    public static Date setMinutes(Date p_date, int p_amount) {
        return set(p_date, Calendar.MINUTE, p_amount);
    }
    
    /**
     * <p>更改日期为指定秒</p>
     * <br>样例:<br>
     * setSeconds(toDate("2010-01-27 10:00:00","yyyy-MM-dd hh:mm:ss"), 20)=Wed Jan 27 10:00:20 CST 2010;<br>
     * @param p_date Date 日期对象
     * @param p_amount int 秒
     * @return Date 日期对象
     */
    public static Date setSeconds(Date p_date, int p_amount) {
        return set(p_date, Calendar.SECOND, p_amount);
    }
    
    /**
     * <p>更改日期为指定毫秒</p>
     * <br>样例:<br>
     * setMilliseconds(toDate("2010-01-27 10:00:00","yyyy-MM-dd hh:mm:ss"), 9000)=Wed Jan 27 10:00:09 CST 2010;<br>
     * @param p_date Date 日期对象
     * @param p_amount int 毫秒
     * @return Date 日期对象
     */
    public static Date setMilliseconds(Date p_date, int p_amount) {
        return set(p_date, Calendar.MILLISECOND, p_amount);
    } 

    /**
     * <p>更改日期域的值</p>
     * <br>样例:<br>
     * set(toDate(2010,1,27),Calendar.DAY_OF_MONTH, 5)=Tue Jan 05 00:00:00 CST 2010;<br>
     * @param date 日期对象
     * @param calendarField calendar域 例如：DAY_OF_WEEK 或 DAY_OF_YEAR
     * @param amount 总数
     * @return Date 日期对象
     */
    private static Date set(Date date, int calendarField, int amount) {
        if (date == null) {
            throw new IllegalArgumentException("The date must not be null");
        }
        
        Calendar c = Calendar.getInstance();
        c.setTime(date);
        c.set(calendarField, amount);
        return c.getTime();
    } 
    
    
    /****************************（五）阳历、阴历日期换算**********************************************/	
    // Array lIntLunarDay is stored in the monthly day information in every year
	// from 1901 to 2100 of the lunar calendar,
	// The lunar calendar can only be 29 or 30 days every month, express with
	// 12(or 13) pieces of binary bit in one year,
	// it is 30 days for 1 form in the corresponding location , otherwise it is
	// 29 days
	private static final int[] iLunarmonthDaysTable = {
			0x4ae0,	0xa570,	0x5268,	0xd260,	0xd950,	0x6aa8,	0x56a0,	0x9ad0,	0x4ae8,	0x4ae0, // 1910
			0xa4d8,	0xa4d0,	0xd250,	0xd548,	0xb550,	0x56a0,	0x96d0,	0x95b0,	0x49b8,	0x49b0, // 1920
			0xa4b0,	0xb258,	0x6a50,	0x6d40,	0xada8,	0x2b60,	0x9570,	0x4978,	0x4970,	0x64b0, // 1930
			0xd4a0,	0xea50,	0x6d48,	0x5ad0,	0x2b60,	0x9370,	0x92e0,	0xc968,	0xc950,	0xd4a0, // 1940
			0xda50,	0xb550,	0x56a0,	0xaad8,	0x25d0,	0x92d0,	0xc958,	0xa950,	0xb4a8,	0x6ca0, // 1950
			0xb550,	0x55a8,	0x4da0,	0xa5b0,	0x52b8,	0x52b0,	0xa950,	0xe950,	0x6aa0,	0xad50, // 1960
			0xab50,	0x4b60,	0xa570,	0xa570,	0x5260,	0xe930,	0xd950,	0x5aa8,	0x56a0,	0x96d0, // 1970
			0x4ae8, 0x4ad0,	0xa4d0,	0xd268,	0xd250,	0xd528,	0xb540,	0xb6a0,	0x96d0,	0x95b0, // 1980
			0x49b0, 0xa4b8, 0xa4b0,	0xb258,	0x6a50,	0x6d40,	0xada0,	0xab60,	0x9370,	0x4978, // 1990
			0x4970, 0x64b0, 0x6a50, 0xea50,	0x6b28,	0x5ac0,	0xab60,	0x9368,	0x92e0,	0xc960, // 2000
			0xd4a8, 0xd4a0, 0xda50, 0x5aa8, 0x56a0, 0xaad8, 0x25d0,	0x92d0,	0xc958,	0xa950, // 2010
			0xb4a0, 0xb550, 0xb550, 0x55a8, 0x4ba0, 0xa5b0,	0x52b8,	0x52b0,	0xa930,	0x74a8, // 2020
			0x6aa0, 0xad50, 0x4da8, 0x4b60, 0x9570, 0xa4e0, 0xd260,	0xe930,	0xd530,	0x5aa0, // 2030
			0x6b50, 0x96d0, 0x4ae8, 0x4ad0, 0xa4d0, 0xd258, 0xd250, 0xd520,	0xdaa0,	0xb5a0, // 2040
			0x56d0, 0x4ad8, 0x49b0, 0xa4b8, 0xa4b0, 0xaa50, 0xb528, 0x6d20,	0xada0, 0x55b0  // 2050
	};

	// Array iLunarLeapMonthTable preserves the lunar calendar leap month from
	// 1901 to 2050,
	// if it is 0 express not to have , every byte was stored for two years
	private static final char[] iLunarLeapMonthTable = { 
			0x00, 0x50, 0x04, 0x00, 0x20, // 1910
			0x60, 0x05, 0x00, 0x20, 0x70, // 1920
			0x05, 0x00, 0x40, 0x02, 0x06, // 1930
			0x00, 0x50, 0x03, 0x07, 0x00, // 1940
			0x60, 0x04, 0x00, 0x20, 0x70, // 1950
			0x05, 0x00, 0x30, 0x80, 0x06, // 1960
			0x00, 0x40, 0x03, 0x07, 0x00, // 1970
			0x50, 0x04, 0x08, 0x00, 0x60, // 1980
			0x04, 0x0a, 0x00, 0x60, 0x05, // 1990
			0x00, 0x30, 0x80, 0x05, 0x00, // 2000
			0x40, 0x02, 0x07, 0x00, 0x50, // 2010
			0x04, 0x09, 0x00, 0x60, 0x04, // 2020
			0x00, 0x20, 0x60, 0x05, 0x00, // 2030
			0x30, 0xb0, 0x06, 0x00, 0x50, // 2040
			0x02, 0x07, 0x00, 0x50, 0x03  // 2050
	};

	// Array iSolarLunarTable stored the offset days
	// in New Year of solar calendar and lunar calendar from 1901 to 2050;
	private static final char[] iSolarLunarOffsetTable = {
			49, 38, 28, 46, 34,	24, 43, 32, 21, 40, // 1910
			29, 48, 36, 25, 44, 34, 22, 41, 31, 50, // 1920
			38, 27, 46, 35, 23, 43, 32, 22, 40, 29, // 1930
			47, 36, 25, 44, 34, 23, 41, 30, 49, 38, // 1940
			26, 45, 35, 24, 43, 32, 21, 40, 28, 47, // 1950
			36, 26, 44, 33, 23, 42, 30, 48, 38, 27, // 1960
			45, 35, 24, 43, 32, 20, 39, 29, 47, 36, // 1970
			26, 45, 33, 22, 41, 30, 48, 37, 27, 46, // 1980
			35, 24, 43, 32, 50, 39, 28, 47, 36, 26, // 1990
			45, 34, 22, 40, 30, 49, 37, 27, 46, 35, // 2000
			23, 42, 31, 21, 39, 28, 48, 37, 25, 44, // 2010
			33, 23, 41, 31, 50, 39, 28, 47, 35, 24, // 2020
			42, 30, 21, 40, 28, 47, 36, 25, 43, 33, // 2030
			22, 41, 30, 49, 37, 26, 44, 33, 23, 42, // 2040
			31, 21, 40, 29, 47, 36, 25, 44, 32, 22  // 2050
	};

	/**
	 * <p>判断该年是否是闰年</p>
	 * <p>样例</p>
	 * bIsSolarLeapYear(2008) = true;<br>
	 * bIsSolarLeapYear(2010) = false;<br>
	 * @param p_iYear 指定年份
	 * @return true闰年; false平年
	 * @throws Exception 遇到非法年份参数时，抛出异常
	 */
	public static boolean bIsSolarLeapYear(int p_iYear) throws Exception {
		if (p_iYear < 1901 || p_iYear > 2050)
			throw new Exception("年份【" + p_iYear + "】是一个非法数值，应在【1901~2050】");
		return ((p_iYear % 4 == 0) && (p_iYear % 100 != 0) || p_iYear % 400 == 0);
	}

	/**
	 * <p>根据指定阳历年月获取该月天数</p>
	 * <p>样例</p>
	 * iGetSYearmonthDays(2008, 1) = 31;<br>
	 * iGetSYearmonthDays(2008, 2) = 29;<br>
	 * iGetSYearmonthDays(2008, 4) = 30;<br>
	 * iGetSYearmonthDays(2009, 1) = 31;<br>
	 * iGetSYearmonthDays(2009, 2) = 28;<br>
	 * iGetSYearmonthDays(2009, 4) = 30;<br>
	 * @param p_iYear 指定年份
	 * @param p_iMonth 指定月份
	 * @return int 指定的阳历年月的该月天数
	 * @throws Exception 遇到非法年份参数、月份参数时，抛出异常
	 */
	public static int iGetSYearmonthDays(int p_iYear, int p_iMonth) throws Exception {
		if (p_iYear < 1901 || p_iYear > 2050)
			throw new Exception("年份【" + p_iYear + "】是一个非法数值，应在【1901~2050】");
		if (p_iMonth < 1 || p_iMonth > 12)
			throw new Exception("月份【" + p_iMonth + "】是一个非法数值，应在【1~12】");
		if ((p_iMonth == 1) || (p_iMonth == 3) || (p_iMonth == 5) || (p_iMonth == 7)
				|| (p_iMonth == 8) || (p_iMonth == 10) || (p_iMonth == 12))
			return 31;
		else if ((p_iMonth == 4) || (p_iMonth == 6) || (p_iMonth == 9)
				|| (p_iMonth == 11))
			return 30;
		else if (p_iMonth == 2) {
			if (bIsSolarLeapYear(p_iYear))
				return 29;
			else
				return 28;
		} else
			return 0;
	}

	/**
	 * <p>计算从指定年份阳历1月1日起，截止到该年指定日期，共有多少天</p>
	 * <p>样例</p>
	 * iGetSNewYearOffsetDays(2008, 1, 1) = 0; <br>
	 * iGetSNewYearOffsetDays(2008, 3, 1) = 60; <br>
	 * iGetSNewYearOffsetDays(2008, 12, 31) = 366; <br>
	 * iGetSNewYearOffsetDays(2010, 1, 1) = 0; <br>
	 * iGetSNewYearOffsetDays(2010, 3, 1) = 59; <br>
	 * iGetSNewYearOffsetDays(2010, 12, 31) = 365; <br>
	 * @param p_iYear 指定年份
	 * @param p_iMonth 指定月份
	 * @param p_iDay 指定天数
	 * @return int 计算后的天数
	 * @throws Exception 遇到非法年份参数、月份参数、日期参数时，抛出异常
	 */
	public static int iGetSNewYearOffsetDays(int p_iYear, int p_iMonth, int p_iDay) throws Exception {
		if (p_iYear < 1901 || p_iYear > 2050)
			throw new Exception("年份【" + p_iYear + "】是一个非法数值，应在【1901~2050】");
		if (p_iMonth < 1 || p_iMonth > 12)
			throw new Exception("月份【" + p_iMonth + "】是一个非法数值，应在【1~12】");
		int _iDay = iGetSYearmonthDays(p_iYear, p_iMonth);
		if (p_iMonth < 1 || p_iDay > _iDay)
			throw new Exception("日期【" + p_iDay + "】是一个非法数值，应在【1~" + _iDay + "】");
		int _iOffsetDays = 0;
		for (int i = 1; i < p_iMonth; i++) {
			_iOffsetDays += iGetSYearmonthDays(p_iYear, i);
		}
		_iOffsetDays += p_iDay - 1;
		return _iOffsetDays;
	}

	/**
	 * <p>获取农历闰年的闰月月份</p>
	 * <p>样例</p>
	 * iGetLLeapMonth(2008) = 0; <br>
	 * iGetLLeapMonth(2009) = 5; <br>
	 * @param p_iYear 指定年份
	 * @return int 农历闰月月份
	 * @throws Exception 遇到非法年份参数时，抛出异常
	 */
	public static int iGetLLeapMonth(int p_iYear) throws Exception {
		if (p_iYear < 1901 || p_iYear > 2050)
			throw new Exception("年份【" + p_iYear + "】是一个非法数值，应在【1901~2050】");
		char p_iMonth = iLunarLeapMonthTable[(p_iYear - 1901) / 2];
		if (p_iYear % 2 == 0)
			return (p_iMonth & 0x0f);
		else
			return (p_iMonth & 0xf0) >> 4;
	}

	/**
	 * <p>根据指定农历年月获取该月天数</p>
	 * <p>样例</p>
	 * iGetLMonthDays(2008, 1) = 30;<br>
	 * iGetLMonthDays(2008, 2) = 29;<br>
	 * iGetLMonthDays(2008, 3) = 29;<br>
	 * iGetLMonthDays(2009, 1) = 30;<br>
	 * iGetLMonthDays(2009, 2) = 30;<br>
	 * iGetLMonthDays(2009, 3) = 29;<br>
	 * @param p_iYear 指定年份
	 * @param p_iMonth 指定月份
	 * @return int 指定的农历年月的该月天数
	 * @throws Exception 遇到非法年份参数时，抛出异常
	 */
	public static int iGetLMonthDays(int p_iYear, int p_iMonth) throws Exception {
		if (p_iYear < 1901 || p_iYear > 2050)
			throw new Exception("年份【" + p_iYear + "】是一个非法数值，应在【1901~2050】");
		int _iLeapMonth = iGetLLeapMonth(p_iYear);
		if ((p_iMonth > 12) && (p_iMonth - 12 != _iLeapMonth) || (p_iMonth < 0)) {
			System.out.println("Wrong month, ^_^ , i think you are want a -1, go to death!");
			return -1;
		}
		if (p_iMonth - 12 == _iLeapMonth) {
			if ((iLunarmonthDaysTable[p_iYear - 1901] & (0x8000 >> _iLeapMonth)) == 0)
				return 29;
			else
				return 30;
		}
		if ((_iLeapMonth > 0) && (p_iMonth > _iLeapMonth))
			p_iMonth++;
		if ((iLunarmonthDaysTable[p_iYear - 1901] & (0x8000 >> (p_iMonth - 1))) == 0)
			return 29;
		else
			return 30;
	}

	/**
	 * <p>计算该农历年份有多少天</p>
	 * <p>样例</p>
	 * iGetLYearDays(2008) = 354;<br>
	 * iGetLYearDays(2009) = 355;<br>
	 * iGetLYearDays(2010) = 354;<br>
	 * @param p_iYear 指定年份
	 * @return int 该年有多少天
	 * @throws Exception 遇到非法年份参数时，抛出异常
	 */
	public static int iGetLYearDays(int p_iYear) throws Exception {
		if (p_iYear < 1901 || p_iYear > 2050)
			throw new Exception("年份【" + p_iYear + "】是一个非法数值，应在【1901~2050】");
		int _iYearDays = 0;
		int _iLeapMonth = iGetLLeapMonth(p_iYear);
		for (int i = 1; i < 13; i++)
			try {
				_iYearDays += iGetLMonthDays(p_iYear, i);
			} catch (Exception e) {
				e.printStackTrace();
			}
		if (_iLeapMonth > 0)
			try {
				_iYearDays += iGetLMonthDays(p_iYear, _iLeapMonth + 12);
			} catch (Exception e) {
				e.printStackTrace();
			}
		return _iYearDays;
	}

	/**
	 * <p>计算从指定年份农历1月1日起，截止到该年指定农历日期，共有多少天</p>
	 * <p>样例</p>
	 * iGetLNewYearOffsetDays(2008, 1, 1) = 0; <br>
	 * iGetLNewYearOffsetDays(2008, 3, 1) = 59; <br>
	 * iGetLNewYearOffsetDays(2008, 12, 31) = 354; <br>
	 * iGetLNewYearOffsetDays(2009, 1, 1) = 0; <br>
	 * iGetLNewYearOffsetDays(2009, 3, 1) = 60; <br>
	 * iGetLNewYearOffsetDays(2009, 12, 31) = 384; <br>
	 * @param p_iYear 指定年份
	 * @param p_iMonth 指定月份
	 * @param p_iDay 指定天数
	 * @return 计算后的结果
	 * @throws Exception 遇到非法年份参数、月份参数或日期参数时，抛出异常
	 */
	public static int iGetLNewYearOffsetDays(int p_iYear, int p_iMonth, int p_iDay) throws Exception {
		if (p_iYear < 1901 || p_iYear > 2050)
			throw new Exception("年份【" + p_iYear + "】是一个非法数值，应在【1901~2050】");
		if (p_iMonth < 1 || p_iMonth > 12)
			throw new Exception("月份【" + p_iMonth + "】是一个非法数值，应在【1~12】");
		int _iDay = iGetSYearmonthDays(p_iYear, p_iMonth);
		if (p_iMonth < 1 || p_iDay > _iDay)
			throw new Exception("日期【" + p_iDay + "】是一个非法数值，应在【1~" + _iDay + "】");
		int _iOffsetDays = 0;
		int iLeapMonth = iGetLLeapMonth(p_iYear);
		if ((iLeapMonth > 0) && (iLeapMonth == p_iMonth - 12)) {
			p_iMonth = iLeapMonth;
			_iOffsetDays += iGetLMonthDays(p_iYear, p_iMonth);
		}
		for (int i = 1; i < p_iMonth; i++) {
			_iOffsetDays += iGetLMonthDays(p_iYear, i);
			if (i == iLeapMonth)
				_iOffsetDays += iGetLMonthDays(p_iYear, iLeapMonth + 12);
		}
		_iOffsetDays += p_iDay - 1;
		return _iOffsetDays;
	}

	/**
	 * <p>阳历转换农历</p>
	 * <p>样例</p>
	 * sCalendarSolarToLundar(2010, 2, 14) = 20100101;<br>
	 * sCalendarSolarToLundar(2010, 3, 17) = 20100202;<br>
	 * @param p_iYear 指定年份
	 * @param p_iMonth 指定月份
	 * @param p_iDay 指定天数
	 * @return 转换后的农历日期
	 * @throws Exception 遇到非法年份参数、月份参数或日期参数时，抛出异常
	 */
	public static String sCalendarSolarToLundar(int p_iYear, int p_iMonth, int p_iDay) throws Exception {
		if (p_iYear < 1901 || p_iYear > 2050)
			throw new Exception("年份【" + p_iYear + "】是一个非法数值，应在【1901~2050】");
		if (p_iMonth < 1 || p_iMonth > 12)
			throw new Exception("月份【" + p_iMonth + "】是一个非法数值，应在【1~12】");
		int _iDay = iGetSYearmonthDays(p_iYear, p_iMonth);
		if (p_iMonth < 1 || p_iDay > _iDay)
			throw new Exception("日期【" + p_iDay + "】是一个非法数值，应在【1~" + _iDay + "】");
		int _iLDay, _iLMonth, _iLYear;
		int _iOffsetDays = iGetSNewYearOffsetDays(p_iYear, p_iMonth, p_iDay);
		int _iLeapMonth = iGetLLeapMonth(p_iYear);
		if (_iOffsetDays < iSolarLunarOffsetTable[p_iYear - 1901]) {
			_iLYear = p_iYear - 1;
			_iOffsetDays = iSolarLunarOffsetTable[p_iYear - 1901] - _iOffsetDays;
			_iLDay = _iOffsetDays;
			for (_iLMonth = 12; _iOffsetDays > iGetLMonthDays(_iLYear, _iLMonth); _iLMonth--) {
				_iLDay = _iOffsetDays;
				_iOffsetDays -= iGetLMonthDays(_iLYear, _iLMonth);
			}
			if (0 == _iLDay)
				_iLDay = 1;
			else
				_iLDay = iGetLMonthDays(_iLYear, _iLMonth) - _iOffsetDays + 1;
		} else {
			_iLYear = p_iYear;
			_iOffsetDays -= iSolarLunarOffsetTable[p_iYear - 1901];
			_iLDay = _iOffsetDays + 1;
			for (_iLMonth = 1; _iOffsetDays >= 0; _iLMonth++) {
				_iLDay = _iOffsetDays + 1;
				_iOffsetDays -= iGetLMonthDays(_iLYear, _iLMonth);
				if ((_iLeapMonth == _iLMonth) && (_iOffsetDays > 0)) {
					_iLDay = _iOffsetDays;
					_iOffsetDays -= iGetLMonthDays(_iLYear, _iLMonth + 12);
					if (_iOffsetDays <= 0) {
						_iLMonth += 12 + 1;
						break;
					}
				}
			}
			_iLMonth--;
		}
		return "" + _iLYear + (_iLMonth > 9 ? "" + _iLMonth : "0" + _iLMonth) + (_iLDay > 9 ? "" + _iLDay : "0" + _iLDay);
	}

	/**
	 * <p>农历转换阳历</p>
	 * <p>样例</p>
	 * sCalendarLundarToSolar(2010, 1, 1) = 20100214;<br>
	 * sCalendarLundarToSolar(2010, 2, 2) = 20100317;<br>
	 * @param p_iYear 指定年份
	 * @param p_iMonth 指定月份
	 * @param p_iDay 指定天数
	 * @return 转换后的阳历日期
	 * @throws Exception 遇到非法年份参数、月份参数或日期参数时，抛出异常
	 */
	public static String sCalendarLundarToSolar(int p_iYear, int p_iMonth, int p_iDay) throws Exception {
		if (p_iYear < 1901 || p_iYear > 2050)
			throw new Exception("年份【" + p_iYear + "】是一个非法数值，应在【1901~2050】");
		if (p_iMonth < 1 || p_iMonth > 12)
			throw new Exception("月份【" + p_iMonth + "】是一个非法数值，应在【1~12】");
		int _iDay = iGetSYearmonthDays(p_iYear, p_iMonth);
		if (p_iMonth < 1 || p_iDay > _iDay)
			throw new Exception("日期【" + p_iDay + "】是一个非法数值，应在【1~" + _iDay + "】");
		int _iSYear, _iSMonth, _iSDay;
		int _iOffsetDays = iGetLNewYearOffsetDays(p_iYear, p_iMonth, p_iDay) + iSolarLunarOffsetTable[p_iYear - 1901];
		int iYearDays = bIsSolarLeapYear(p_iYear) ? 366 : 365;
		if (_iOffsetDays >= iYearDays) {
			_iSYear = p_iYear + 1;
			_iOffsetDays -= iYearDays;
		} else {
			_iSYear = p_iYear;
		}
		_iSDay = _iOffsetDays + 1;
		for (_iSMonth = 1; _iOffsetDays >= 0; _iSMonth++) {
			_iSDay = _iOffsetDays + 1;
			_iOffsetDays -= iGetSYearmonthDays(_iSYear, _iSMonth);
		}
		_iSMonth--;
		return "" + _iSYear + (_iSMonth > 9 ? _iSMonth + "" : "0" + _iSMonth) + (_iSDay > 9 ? _iSDay + "" : "0" + _iSDay);
	}
	
	/**
	 * 方法名:diffTwoDateSeconds
	 * 方法作用:比较两时间想差秒数
	 * @param b_date	开始时间
	 * @param e_date 	结束时间
	 * @param sule	格式化规则
	 * @return
	 */
	public static long diffTwoDateSeconds(String b_date, String e_date, String sule) {
		long diff = 0;
		Date beg_date = StringToDate(sule, b_date);
		Date end_date = StringToDate(sule, e_date);
		diff = diffTwoDateSeconds(beg_date,end_date);
		return diff;
	}
	
	/**
	 * 方法名:diffTwoDateSeconds
	 * 方法作用:比较两时间想差秒数
	 * @param b_date	开始时间
	 * @param e_date 	结束时间
	 * @param sule	格式化规则
	 * @return
	 */
	public static long diffTwoDateSeconds(Date b_date, Date e_date) {
		long diff = 0;
		diff = (b_date.getTime() - e_date.getTime()) / 1000;
		if (diff < 0) diff = 0 - diff;
		return diff;
	}
}
